package ldh.text.controller;

import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.Pane;
import javafx.stage.FileChooser;
import ldh.text.pane.BigDataTextAreaPane;
import ldh.text.pane.SmallDataTextAreaPane;
import ldh.text.util.FileSizeUtil;
import ldh.text.util.RegionUtil;
import ldh.text.util.ThreadPoolUtil;
import org.fxmisc.richtext.Selection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class MainController implements Initializable {

    private static final Logger LOGGER = LoggerFactory.getLogger(MainController.class);

    private FileChooser fileChooser = new FileChooser();

    @FXML private TabPane contentTabPane;
    @FXML private CheckMenuItem wrapCheck;
    @FXML private MenuItem newFileMenuItem;   // 新建
    @FXML private MenuItem openFileMenuItem;
    @FXML private MenuItem saveFileMenuItem;
    @FXML private MenuItem saveNewFileMenuItem;

    public void newFile(ActionEvent actionEvent) {
        addNewTab();
    }

    @FXML
    public void openFile(ActionEvent actionEvent) {
        File file = fileChooser.showOpenDialog(contentTabPane.getScene().getWindow());
        if (file == null || file.isDirectory()) return;
        addNewTab(file);
    }

    @FXML
    public void save(ActionEvent actionEvent) {
        Tab tab = contentTabPane.getSelectionModel().getSelectedItem();
        Node node = tab.getContent();
        if (node instanceof SmallDataTextAreaPane) {
            SmallDataTextAreaPane smallDataTextAreaPane = (SmallDataTextAreaPane) node;
            File file = smallDataTextAreaPane.saveData();
            if (file != null) {
                tab.setText(file.getName());
            }
        }
    }

    public void saveForNew(ActionEvent actionEvent) {
    }

    public void exit(ActionEvent actionEvent) {
        close();
        RegionUtil.getStage().close();
        System.exit(0);
    }

    public void close(){
        contentTabPane.getTabs().forEach(t->{
            if (t.getContent() instanceof BigDataTextAreaPane) {
                BigDataTextAreaPane bigDataTextAreaPane = (BigDataTextAreaPane) t.getContent();
                bigDataTextAreaPane.close();
            } else if (t.getContent() instanceof SmallDataTextAreaPane) {
                SmallDataTextAreaPane samllDataTextAreaPane = (SmallDataTextAreaPane) t.getContent();
                samllDataTextAreaPane.close();
            }
        });
    }

    private void addNewTab(File file) {
        try {
            long fileSize = FileSizeUtil.getFileSize(file.toPath());
            if (fileSize < 20 * 1024 * 1024) {
                SmallDataTextAreaPane bigDataTextArea = new SmallDataTextAreaPane(file);
                Tab tab = new Tab(file.getName(), bigDataTextArea);
                contentTabPane.getTabs().add(tab);
                contentTabPane.getSelectionModel().select(tab);
                bigDataTextArea.loadData(wrapCheck.isSelected());
            } else {
                BigDataTextAreaPane bigDataTextArea = new BigDataTextAreaPane(file);
                Tab tab = new Tab(file.getName(), bigDataTextArea);
                contentTabPane.getTabs().add(tab);
                contentTabPane.getSelectionModel().select(tab);
                bigDataTextArea.loadData(wrapCheck.isSelected());
            }
        } catch (Exception e) {
            LOGGER.error("获取文件大小失败", e);
        }
    }

    private void addNewTab() {
        SmallDataTextAreaPane smallDataTextAreaPane = new SmallDataTextAreaPane();
        Tab tab = new Tab("mini-undefined", smallDataTextAreaPane);
        contentTabPane.getTabs().add(tab);
        contentTabPane.getSelectionModel().select(tab);
    }

//    private void addNewTab(File file) {
////        StyleClassedTextArea textArea = new StyleClassedTextArea();
////        textArea.setParagraphGraphicFactory(LineNumberFactory.get(textArea));
////        contentTabPane.widthProperty().addListener(l->textArea.setPrefWidth(contentTabPane.getWidth()));
////        textArea.setOnKeyPressed(e->{
////            if (e.isControlDown()) {
////                isCtrlDown = true;
////            }
////        });
////        textArea.setOnKeyReleased(e->{
////            if(!e.isControlDown()) {
////                isCtrlDown = false;
////            }
////        });
////        textArea.setOnMouseClicked(e->{
////            textArea.deselect();
////            LOGGER.info("clicked: caretPoint:{}, paragraph:{}, column:{}", textArea.getCaretPosition(),
////                    textArea.getCurrentParagraph(), textArea.getCaretColumn());
////
//////            textArea.addSelection(new SelectionImpl<>("dd" +  textArea.getCurrentParagraph(), textArea,
//////                    textArea.getAbsolutePosition(textArea.getCurrentParagraph(), 0), textArea.getCaretPosition()));
////            if(clickPoint == null){
////                clickPoint = new ClickPoint(textArea.getCurrentParagraph(), textArea.getCaretColumn(), textArea.getCaretPosition());
////            } else {
////                for(Selection selection : selectionList) {
////                    textArea.removeSelection(selection);
////                }
////                int currentParagraph = textArea.getCurrentParagraph();
////                int caretColumn = textArea.getCaretColumn();
////
////                for (int i=clickPoint.getParagraph(); i<=currentParagraph; i++) {
////                    int anchor = textArea.getAbsolutePosition(i, clickPoint.getColumn());
////                    int caretPosition = textArea.getAbsolutePosition(i, caretColumn);
////                    Selection selection = new SelectionImpl<>("dd" + i, textArea, anchor, caretPosition);
////                    textArea.addSelection(selection);
////                    selectionList.add(selection);
//////                    textArea.selectRange(i, clickPoint.getColumn(), i, caretColumn);
////                }
////                if (!isCtrlDown) {
////                    clickPoint = null;
////                }
////            }
////        });
////
////        currentTextArea = textArea;
////        VirtualizedScrollPane virtualizedScrollPane = new VirtualizedScrollPane(textArea);
////        virtualizedScrollPane.estimatedScrollYProperty().addListener(l->{
////            ScrollBar scrollBar = (ScrollBar) virtualizedScrollPane.lookup("ScrollBar:vertical");
////            LOGGER.info("scroll Y : {}, {}, {}", virtualizedScrollPane.getEstimatedScrollY(),
////                    ((double)virtualizedScrollPane.totalHeightEstimateProperty().getOrElse(0.0)) - virtualizedScrollPane.getEstimatedScrollY(),
////                    scrollBar.getValue() + virtualizedScrollPane.getEstimatedScrollY());
////
////            virtualizedScrollPane.lookup("scroll-bar");
////        });
////        Tab tab = new Tab(file.getName(), virtualizedScrollPane);
////        contentTabPane.getTabs().add(tab);
////        contentTabPane.getSelectionModel().select(tab);
////        ThreadPoolUtil.submit(()->{
////            try {
////                long size = Files.size(file.toPath());
////                if (size < 10 * 1024 * 1024) {
////                    byte[] data = Files.readAllBytes(file.toPath());
////                    String content = new String(data, "utf8");
////                    Platform.runLater(()->{
////                        textArea.insertText(0, content);
////                    });
////                } else {
////                    RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
////                    FileChannel fileChannel = randomAccessFile.getChannel();
////                    ByteBuffer byteBuffer = ByteBuffer.allocate(10 * 1024 * 1024);
////                    fileChannel.read(byteBuffer);
////                    byteBuffer.flip();
////                    String content = new String(byteBuffer.array(), "utf8");
////                    Platform.runLater(()->{
////                        textArea.insertText(0, content);
////                    });
////                    fileChannel.close();
////                    randomAccessFile.close();
////                }
////            } catch (Exception e) {
////                LOGGER.error("open file error", e);
////            }
////        });
////    }

    @FXML
    public void wrapLine(ActionEvent actionEvent) {
        contentTabPane.getTabs().forEach(t->{
            if (t.getContent() instanceof BigDataTextAreaPane) {
                BigDataTextAreaPane bigDataTextAreaPane = (BigDataTextAreaPane) t.getContent();
                bigDataTextAreaPane.setWrapText(wrapCheck.isSelected());
            } else if(t.getContent() instanceof SmallDataTextAreaPane) {
                SmallDataTextAreaPane smallDataTextAreaPane = (SmallDataTextAreaPane) t.getContent();
                smallDataTextAreaPane.setWrapText(wrapCheck.isSelected());
            }
        });
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        newFileMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.N, KeyCombination.CONTROL_DOWN));
        openFileMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.O, KeyCombination.CONTROL_DOWN));
        saveFileMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN));
        saveNewFileMenuItem.setAccelerator(new KeyCodeCombination(KeyCode.A, KeyCombination.CONTROL_DOWN));
    }

}
